package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.VO.ErrorResult;
import com.tanhua.model.VO.MovementsVo;
import com.tanhua.model.VO.PageResult;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @auther ll
 * @date 2022/3/29  9:43
 */
@Service
public class MovementService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 发布动态
     */
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1.判断发布动态的内容是否存在
        if (StringUtils.isEmpty(movement.getTextContent())){
            //判断是空的就说明没有内容 就抛出一个异常
            throw new BusinessException(ErrorResult.contentError());
        }
        //2.获取当前登录的用户的id
        Long userId = UserHolder.getUserId();
        //3.将文件内容上床到阿里云oss 获取请求地址
        List<String> medias = new ArrayList<>();  //建一个集合 用来装地址
        for (MultipartFile multipartFile : imageContent) {
            //获取地址
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            //将地址都假如集合
            medias.add(upload);
        }
        //4.将数据封装到movement对象
        movement.setUserId(userId);
        movement.setMedias(medias);
        //5.调用api完成发布
        movementApi.publish(movement);
    }

    //查询个人动态
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //1、根据用户id，调用API查询个人动态内容（PageResult  -- Movement）
        PageResult pr = movementApi.findByUserId(userId,page,pagesize);
        //2、获取PageResult中的item列表对象
        List<Movement> items = (List<Movement>) pr.getItems();
        //3、非空判断
        if(items == null) {
            return pr;
        }
        //4、循环数据列表
        UserInfo userInfo = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            //5、一个Movement构建一个Vo对象
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        //6、构建返回值
        pr.setItems(vos);
        return pr;
    }

    /**
     *查询好友动态
     */
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        //1.获取当前用户的id
        Long userId = UserHolder.getUserId();
        //2.调用api查询当前用户好友发布的动态列表
        List<Movement> list = movementApi.findFriendMovements(page,pagesize,userId);
        return getPageResult(page, pagesize, list);
    }


    //查询推荐动态
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        //1.从redis获取推荐数据
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //2.判断数据是否存在
        List<Movement> list = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)){
            //3.如果不存在，调用api随机构造10条动态
            list = movementApi.rondomMovements(pagesize);
        }else {
            //4.如果存在 处理pid数据
            String[] values = redisValue.split(",");  //把redisValue里的数据用分割成数组
            //判断当前页的条数是否小于数组总数
            if ((page - 1) * pagesize < redisValue.length()){
                List<Long> pids = Arrays.stream(values).skip((page - 1 ) * pagesize).limit(pagesize)
                        .map(e->Long.valueOf(e))  //将每一个元素转化成long类型
                        .collect(Collectors.toList());  //转化成list数组
                //5.调用api根据pid查询动态数据
                list = movementApi.finfMovementsByPids(pids);
            }
        }
        //6.调用公告方法构造返回值
        return getPageResult(page,pagesize,list);
    }


    //公共方法
    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> list) {
        //3.判断列表是否为空
        if (CollUtil.isEmpty(list)){
            return new PageResult();
        }
        //4.提取动态发布人的id列表
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //5.根据用户id列表获取用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);
        //6.一个movement构造一个vo对象
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = map.get(movement.getUserId());
            if (userInfo != null){
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                vos.add(vo);
            }
        }
        //7.构造RageResult并返回
        return new PageResult(page, pagesize,0l,vos);
    }

}
